import type { Context, Next } from 'hono'
import { createHash, timingSafeEqual } from 'node:crypto'

// Simple API key authentication for admin endpoints
// In production, consider using JWT or more sophisticated auth
const ADMIN_API_KEY = process.env.ADMIN_API_KEY || 'dev-admin-key-change-in-production'

function hashApiKey(key: string): Buffer {
  return createHash('sha256').update(key).digest()
}

// Constant-time comparison to prevent timing attacks
function verifyApiKey(provided: string, expected: string): boolean {
  try {
    const providedHash = hashApiKey(provided)
    const expectedHash = hashApiKey(expected)
    return timingSafeEqual(providedHash, expectedHash)
  } catch {
    return false
  }
}

export function requireAuth() {
  return async (c: Context, next: Next) => {
    const authHeader = c.req.header('Authorization')
    
    if (!authHeader) {
      return c.json({ 
        error: 'Unauthorized', 
        message: 'Authorization header required. Use: Authorization: Bearer <api-key>' 
      }, 401)
    }

    const token = authHeader.replace(/^Bearer\s+/i, '')
    
    if (!token || !verifyApiKey(token, ADMIN_API_KEY)) {
      // Log failed auth attempts for security monitoring
      console.warn(`[security] Failed authentication attempt from ${c.req.header('x-forwarded-for') || 'unknown'}`)
      return c.json({ 
        error: 'Unauthorized', 
        message: 'Invalid API key' 
      }, 401)
    }

    // Log successful auth for audit trail
    console.info(`[auth] Authenticated admin request to ${c.req.path}`)
    await next()
  }
}

// Rate limiting middleware (simple in-memory implementation)
const requestCounts = new Map<string, { count: number; resetTime: number }>()

export function rateLimit(maxRequests = 100, windowMs = 60000) {
  return async (c: Context, next: Next) => {
    const clientId = c.req.header('x-forwarded-for') || c.req.header('x-real-ip') || 'unknown'
    const now = Date.now()
    
    const record = requestCounts.get(clientId)
    
    if (!record || now > record.resetTime) {
      // Reset or create new record
      requestCounts.set(clientId, { count: 1, resetTime: now + windowMs })
    } else {
      record.count++
      if (record.count > maxRequests) {
        return c.json({ 
          error: 'Too Many Requests', 
          message: `Rate limit exceeded. Max ${maxRequests} requests per ${windowMs/1000} seconds.`,
          retryAfter: Math.ceil((record.resetTime - now) / 1000)
        }, 429)
      }
    }
    
    await next()
  }
}

// CSRF protection for state-changing operations
export function csrfProtection() {
  return async (c: Context, next: Next) => {
    const method = c.req.method.toUpperCase()
    
    // Only check CSRF for state-changing methods
    if (['POST', 'PUT', 'DELETE', 'PATCH'].includes(method)) {
      const csrfToken = c.req.header('X-CSRF-Token')
      const expectedToken = c.req.header('X-Requested-With')
      
      // Simple CSRF check - require either CSRF token or XMLHttpRequest header
      if (!csrfToken && expectedToken !== 'XMLHttpRequest') {
        return c.json({ 
          error: 'CSRF Protection', 
          message: 'CSRF token required for state-changing operations. Include X-CSRF-Token header or X-Requested-With: XMLHttpRequest' 
        }, 403)
      }
    }
    
    await next()
  }
}
